//-WinterFramework ? WinterFeather
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using System;
using System.IO;


public class SceneManager : SingleMono<SceneManager>
{
    public string loadedScene = "";

    //string scenesAssetsPath = Path.Combine(Application.streamingAssetsPath, "Scenes");

    public Action<AsyncOperation> onLoadingStart, onLoadingEnd;

    bool isLoading;

    Action onScenesLoad;
    AssetBundle openingSceneBundle, currentSceneBundle;


    
    public new void Awake()
    {
        base.Awake();
        UnityEngine.SceneManagement.SceneManager.sceneLoaded += SceneManager_sceneLoaded;
    }
    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        onScenesLoad?.Invoke();
        onScenesLoad = null;
    }
    public void AddLocalSceneMgr<T>()where T:BaseScene{
        GameObject go = new GameObject(typeof(T).ToString());
        go.AddComponent<T>();
    }
    public void LoadScene<T>(string sceneName) where T : BaseScene {

        StartCoroutine(LoadSceneAsync<T>(sceneName));
    }

    public void ResetScene<T>(string sceneName) where T : BaseScene
    {
        StartCoroutine(ResetSceneAsync<T>(sceneName));
    }

    public IEnumerator ResetSceneAsync<T>(string sceneName) where T : BaseScene
    {
        //if (isloading)
        //{
        //    Debug.LogWarning("SceneMgr isLoading");
        //    yield break;
        //}

        onScenesLoad += () => { AddLocalSceneMgr<T>(); };
        AsyncOperation ao = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneName);
       
        isLoading = true;

        onLoadingStart?.Invoke(ao);

        yield return ao;

        isLoading = false;

        if (currentSceneBundle != null) currentSceneBundle.Unload(true);
        currentSceneBundle = openingSceneBundle;

        loadedScene = sceneName;

        Debug.Log("onLoadingEnd");
        onLoadingEnd?.Invoke(ao);
    }

    public IEnumerator LoadSceneAsync<T>(string sceneName) where T : BaseScene
    {
        Debug.Log("LoadScene:" + sceneName);

        if (isLoading)
        {
            Debug.Log("SceneMgr isLoading");
            yield break;
        }
        if (loadedScene.Equals(sceneName))
        {
            Debug.Log("Scene " + sceneName + " is already loaded.");
            yield break;
        }
        Debug.Log("if Resource not contain scene, check AssetsBundle");
        //if (!ContainScene(sceneName))
        //{
        //    openningSeneceBundle = AssetsBundleMgr.Instance.LoadAssets(scenesAsstesPath, sceneName);
        //    if (openningSeneceBundle == null) yield break;
        //}

        onScenesLoad += () => { AddLocalSceneMgr<T>(); };
        AsyncOperation ao = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneName);

        isLoading = true;

        onLoadingStart?.Invoke(ao);

        while (!ao.isDone)
        {
            Debug.Log("Loading progress: " + ao.progress);
            yield return null;
        }

        isLoading = false;

        if (currentSceneBundle != null) currentSceneBundle.Unload(true);
        currentSceneBundle = openingSceneBundle;
      
        loadedScene = sceneName;

        Debug.Log("onLoadingEnd");
        onLoadingEnd?.Invoke(ao);
    }
    private bool ContainScene(string sceneName)
    {
        int sceneCount = UnityEngine.SceneManagement.SceneManager.sceneCountInBuildSettings;

        for (int i = 0; i < sceneCount; i++)
        {
            string path = SceneUtility.GetScenePathByBuildIndex(i);
            //if (Path.GetFileNameWithoutExtension(path).Equals(sceneName, StringComparison.OrdinalIgnoreCase))
            if (path.Contains(sceneName))
            {
                return true;
            }
        }

        return false;
    }
    public IEnumerator UnloadScene()
    {
        if (loadedScene != "")
        {
            yield return UnityEngine.SceneManagement.SceneManager.UnloadSceneAsync(loadedScene);
            Debug.Log("UnLoadAssets");
            //AssetsBundleMgr.Instance.UnLoadAssetsAsync(loadedScene);
            loadedScene = "";
        }
    }

    public class Debug
    {
        public static void LogError(object s)
        {
            //UnityEngine.Debug.LogError(s);
        }
        public static void Log(object s)
        {
            //UnityEngine.Debug.Log(s);
        }
    }
}

public class BaseScene : SingleMonoScene<BaseScene>
{
    bool isSceneUpdate;
    public bool IsSceneUpdate => isSceneUpdate;
    private void Awake()
    {
        SceneManager.Instance.onLoadingStart += OnCloseScene;
        isSceneUpdate = true;
    }

    private void OnCloseScene(AsyncOperation operation)
    {
        SceneManager.Instance.onLoadingStart -= OnCloseScene;
        StopAllCoroutines();
        isSceneUpdate = false; 
    }

    protected IEnumerator Start()
    {
        yield return null;
        Debug.Log("LocalSceneMgr Start");
        Debug.Log(GetType().ToString());
    }

    

}
